package com.soft.admin.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.soft.admin.common.ElementConst;
import com.soft.admin.dto.MenuDetailCheckedDTO;
import com.soft.admin.dto.RoleDTO;
import com.soft.admin.service.RoleService;
import com.soft.model.ActionColumn;
import com.soft.model.Role;
import com.soft.model.RoleColumn;
import com.soft.support.PageParam;
import com.soft.support.Pager;
import com.soft.util.JsonUtil;

@SuppressWarnings("unchecked")
@Component
public class RoleServiceImpl extends BaseServiceImpl implements RoleService {

	@Transactional(readOnly = true)
	public String get(RoleDTO params, PageParam page) {
		Pager roles = this.getBaseDao().findForPager(Role.class, new Order[]{Order.desc("id")}, 
				page.getStart(), page.getLimit(),
				Restrictions.eq("level", 0),
				Restrictions.like("name", params.getName(), MatchMode.ANYWHERE));
		Pager res = new Pager();
		res.setTotal(roles.getTotal());
		List<RoleDTO> rs = new ArrayList<RoleDTO>();
		for (Object role : roles.getDatas()) {
			RoleDTO dto = new RoleDTO();
			Role rr = (Role)role;
			BeanUtils.copyProperties(rr, dto);
			rs.add(dto);
		}
		res.setDatas(rs);
		return JsonUtil.toStringFromObject(res);
	}

	@Transactional
	public String addOrEdit(RoleDTO params) {
		Role role = null;
		if (params.getId() == null) {
			role = new Role();
			role.setLevel(0);
		} else {
			role = (Role)this.getBaseDao().get(Role.class, params.getId());
		}
		role.setName(params.getName());
		role.setRemark(params.getRemark());
		this.getBaseDao().save(role);
		return JsonUtil.toRes("保存成功！");
	}

	@Transactional
	public String remove(Integer id) {
		this.getBaseDao().delete(Role.class, id);
		return JsonUtil.toRes("删除成功！");
	}

	@Transactional(readOnly = true)
	public String getMenu() {
		List<ActionColumn> acs = this.getBaseDao().findAll(ActionColumn.class, new Order[] {Order.asc("leaf")});
		Map<Integer, MenuDetailCheckedDTO> menuMaps = new HashMap<Integer, MenuDetailCheckedDTO>();
		for (ActionColumn ac : acs) {
			if (menuMaps.containsKey(ac.getId()) || ac.getLevel() == 1) continue;
			MenuDetailCheckedDTO dto = new MenuDetailCheckedDTO();
			dto.setId(ac.getId());
			dto.setText(ac.getName());
			if (ac.getParent() != null){
				dto.setParent(ac.getParent().getId());
			}
			dto.setIcon(ElementConst.ICONPATH + ac.getIcon());
			dto.setAleaf(ac.getLeaf());
			menuMaps.put(ac.getId(), dto);
			menuMaps = this.rebuild(menuMaps, dto);
		}
		List<MenuDetailCheckedDTO> dtos = new ArrayList<MenuDetailCheckedDTO>();
		for (MenuDetailCheckedDTO menu : menuMaps.values()) {
			if (menu.getParent() == 0) {
				dtos.add(menu);
			}
		}
		return JsonUtil.toString(dtos);
	}
	
	/**
	 * 递归构建菜单树形.
	 */
	private Map<Integer, MenuDetailCheckedDTO> rebuild(Map<Integer, MenuDetailCheckedDTO> menuMaps, 
			MenuDetailCheckedDTO doo) {
		if (!menuMaps.containsKey(doo.getParent())) return menuMaps;
		if (doo.getParent() == 0) return menuMaps;
		MenuDetailCheckedDTO dto = menuMaps.get(doo.getParent());
		List<MenuDetailCheckedDTO> lst = dto.getChildren();
		for (MenuDetailCheckedDTO ls : lst) {
			if (ls.getId() == doo.getId()) {
				lst.remove(ls);
				break;
			}
		}
		lst.add(doo);
		dto.setChildren(lst);
		menuMaps.put(doo.getParent(), dto);
		if (dto.getParent() != 0) {
			menuMaps = this.rebuild(menuMaps, dto);
		}
		return menuMaps;
	}

	@Transactional(readOnly = true)
	public String getAction(Integer id) {
		Role role = (Role)this.getBaseDao().get(Role.class, id);
		Set<RoleColumn> rcs = role.getRoleColumns();
		List<Integer> acLst = new ArrayList<Integer>(); 
		for (RoleColumn rc : rcs) {
			acLst.add(rc.getColumn().getId());
		}
		return JsonUtil.toString(acLst);
	}

	@Transactional
	public String config(Integer id, Integer[] rules) {
		Role role = (Role)this.getBaseDao().get(Role.class, id);
		for (Integer rule : rules) {
			ActionColumn ac = (ActionColumn)this.getBaseDao().get(ActionColumn.class, rule);
			RoleColumn rc = new RoleColumn();
			rc.setRole(role);
			rc.setColumn(ac);
			this.getBaseDao().save(rc);
		}
		return JsonUtil.toRes("保存成功！");
	}

}
